package com.golf.server.selection;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 
 *
 * <h3>Mutable state.</h3>
 * <p>
 * room data imuatable
 * users add/reomve gruaded
 * game state is guarded
 * </p>
 * 
 * @author gfloodgate
 */
public class Room implements Serializable
{
	
	/** <code>serialVersionUID</code> for this class. */
	private static final long serialVersionUID = -3961165633855258865L;

	
	/** The name of this room, each room namwe should be unique. */
	private final String name;
	
	/** The type of room. */
	private final RoomType type;

	/** Does this room have a gallery, a.k.a. allow spectators. */
	private final boolean hasGallery;
	
	/** The user that created this room. */
	private final User creator;
	
	
	/** The set of users in this room (including the creator). */
	private final Set<User> users = new HashSet<User>();
	
	
	/**
	 * Create a room with with many defaults.
	 * 
	 * @param name The name of the room.
	 * @param creator The user who is creating this room.
	 * 
	 * @throws IllegalArgumentException If there the user name specified is null.
	 */
	public Room(final String name, final User creator) throws IllegalArgumentException
	{
		this (name, RoomType.PUBLIC, true, creator);
	}
	
	
	/**
	 * Create a room instance.
	 * 
	 * @param name The name of the room.
	 * @param type The type of room that this is.
	 * @param hasGallery Whether or not the room has a gallery.
	 * @param creator The user who is creating this room.
	 * 
	 * @throws IllegalArgumentException If there the user name specified is null.
	 */
	public Room(final String name, final RoomType type, final boolean hasGallery, final User creator) throws IllegalArgumentException
	{
		if (name == null)
		{
			throw new IllegalArgumentException("Room anme cannot be null.");
		}
		
		this.name = name;
		this.type = type;
		this.hasGallery = hasGallery;
		this.creator = creator;
		
		users.add(creator);
	}
	
	
	/**
	 * Get the name of the room.
	 * 
	 * @return The unique room name.
	 */
	public String getName()
	{
		return name;
	}
	
	
	/**
	 * Get the room type.
	 * 
	 * @return The type of room (public or private).
	 */
	public RoomType getType()
	{
		return type;
	}
	
	
	/**
	 * Does this room allow spectators?
	 * 
	 * @return true, if spectators are allowed, false otherwise.
	 */
	public boolean hasGallery()
	{
		return hasGallery;
	}
	
	
	/**
	 * Get the user that created this room.
	 * 
	 * @return The user that created the room.
	 */
	public User getCreator()
	{
		return creator;
	}

	
	/**
	 * Get the (read-only) list of users that are currently in this room.
	 * 
	 * @return The (read-only) list of users 
	 */
	public List<User> listUsers()
	{
		synchronized (users)
		{
			final List<User> copy = new ArrayList<User>(users);
			return Collections.unmodifiableList(copy);
		}
	}
	
	
	/**
	 * Add a user to this room.
	 * 
	 * @param user The user being added to this room.
	 */
	public void addUser(final User user)
	{
		synchronized (users)
		{
			users.add(user);
		}	
	}
	
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean equals(final Object obj) 
	{
		if (obj instanceof Room)
		{
			Room that = (Room)obj;
			if (this.name.equals(that.getName()))
			{
				// A room is equal if it has the same name.
				return true;
			}
		}
		
		return false;
	}


	/**
	 * {@inheritDoc}
	 */
	@Override
	public int hashCode() 
	{
		// The room is unique to it's name, so use that hash code.
		return name.hashCode();
	}
	
}
